package ve.gob.ine.censo.servlet;

import static ve.gob.ine.censo.constante.Constante.NOSELECTED;
import static ve.gob.ine.censo.constante.Constante.REPORTE_AVANCE_COBERTURA_VIVIENDA;
import static ve.gob.ine.censo.constante.Constante.REPORTE_PAGOS;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import ve.gob.ine.censo.dao.ibatis.Conexion;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JRQuery;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.JasperRunManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.design.JRDesignQuery;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.export.JRCsvExporter;
import net.sf.jasperreports.engine.export.JRCsvExporterParameter;
import net.sf.jasperreports.engine.export.JRHtmlExporter;
import net.sf.jasperreports.engine.export.JRHtmlExporterParameter;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRXlsExporter;
import net.sf.jasperreports.engine.xml.JRXmlLoader;

/**
 * 
 * ?reporte=nombre_reporte &tipo=PDF o XLS &ps_parametro parametro de string
 * &pi_parametro parametro de integer
 * 
 * http://localhost:8080/ventapiramidal/gen_rep?reporte=detalle_ven&tipo=PDF&
 * ps_codigo=DARO Servlet implementation class gen_rep
 */

public class gen_rep extends HttpServlet {
	
//	private EntidadDAOImpl entDAO;
//	private MunicipioDAOImpl munDAO;
//	private ParroquiaDAOImpl parrDAO;


	
	
	


	private JRBeanCollectionDataSource collectionDataSource;  

	private String titulo;

	private static final long serialVersionUID = 1L;
	HttpServletRequest req = null;
	HttpServletResponse res = null;
	ServletContext sc = null;
	Connection conn = null;
	Map<String, Object> parameters = null;
	String reporte = "";
	String tipo = "";

	final String rutaReporte = "/static/reportes";
	
	public gen_rep() {
		super();
//        
//		this.entDAO = new EntidadDAOImpl(Conexion.config());
//		this.munDAO = new MunicipioDAOImpl(Conexion.config());
//		this.parrDAO = new ParroquiaDAOImpl(Conexion.config());

	}
	
	// conexion a basedatos
	  public void setConexion() throws ClassNotFoundException{ 
		    try {  

		    	conn = Conexion.config().getConfiguration().getEnvironment().getDataSource().getConnection();
		        //conn = Conexion.config().getDataSource().getConnection();
		        
		        System.out.println("conecta db");

		    } catch(SQLException ex) { System.out.println("Error:" +ex.getMessage()); ex.printStackTrace(); }  
	  }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		
		sc = getServletConfig().getServletContext();
		req = request;
		res = response;

		this.tipo = "PDF";
		this.reporte = "";

		this.parameters = new HashMap<String, Object>();

		try {
			setParametros(request);
		} catch (SQLException e) {
			e.printStackTrace();
		}

		if (this.tipo.toUpperCase().equals("PDF")) {
			System.out.println("entro...");
			generarPdf(this.reporte);
		}

		if (this.tipo.toUpperCase().equals("HTML")) {
			System.out.println("entro...");
			generarHTML(this.reporte);
		}

		if (this.tipo.toUpperCase().equals("XLS")) {
			System.out.println("entro...");
			generarEXCEL(this.reporte);
		}
		
		if (this.tipo.toUpperCase().equals("CSV")) {
			System.out.println("CSV entro...");
			generarCSV(this.reporte);
		}
		
		
		
		if (this.tipo.length() < 1 || this.reporte.length() < 1) {
			ServletOutputStream salida = res.getOutputStream();
			res.setContentType("text/html");
			salida.println("<br>");
			salida.println("<p><b>Falta de Parametros</b></p><br>");
			salida.println("<br>");
			salida.println("/gen_rep?reporte=nombre_reporte<br>");
			salida.println("* &tipo=PDF o XLS<br>");
			salida.println("* &ps_parametro   parametro de string<br>");
			salida.println("* &pi_parametro   parametro de integer<br>");
			salida.println("* http://localhost:8080/rg/gen_rep?reporte=tabamort&tipo=PDF&ps_cedu=2119611&ps_soli=000001");
			salida.println("* http://localhost:8080/ventapiramidal/gen_rep?reporte=detalle_ven&tipo=PDF&ps_codigo=DARO&pi_edad=15<br>");
			salida.println("* http://localhost:8080/rg/gen_rep?reporte=piramide01&tipo=PDF<br>");
			salida.println("* http://localhost:8080/rg/gen_rep?reporte=avance_cobertura_VIVIENDA&tipo=PDF&ps_ANO=2010&ps_MES=08&ps_DIA=27<br>");
			salida.println("* http://localhost:8080/rg/gen_rep?reporte=avance_cobertura_VIVIENDA&tipo=PDF&ps_ANO=2010&ps_MES=08&ps_DIA=28<br>");
			salida.println("* http://localhost:8080/rg/gen_rep?reporte=relacion_cobertura_VIVIENDA&tipo=PDF<br>");
			salida.println("* http://localhost:8080/rg/gen_rep_na?reporte=report2avance_empadronamiento&tipo=HTML&ps_sem_ref=4&ps_sem_acu=4,5,<br>");
			salida.println("<br>");
		}
	}

	@SuppressWarnings({ "rawtypes"})
	public void setParametros(HttpServletRequest request) throws SQLException {

		String mypath = sc.getRealPath(rutaReporte + File.separator);

		parameters.put("ruta", mypath + File.separator);

		String nivel = "Nacional";
		String nivelNombre = "Nacional";



		
		String reporteName = req.getParameter("reporte");

		
		
		if (REPORTE_AVANCE_COBERTURA_VIVIENDA.equalsIgnoreCase(reporteName)) {
			parameters.put("reporte", REPORTE_AVANCE_COBERTURA_VIVIENDA);
			parameters.put("plantilla", "avance_cobertura_VIVIENDA");
			this.titulo = "Viviendas empadronadas " + nivel;

		}else if(REPORTE_PAGOS.equalsIgnoreCase(reporteName)){
			System.out.println("reporteName:"+reporteName);
			parameters.put("reporte", REPORTE_PAGOS);
			parameters.put("plantilla", "pagos");
//			EjecutaPago ejecutaPago = null;//((EjecutaPago) request.getSession().getAttribute("EjecutaPago"));
//			this.collectionDataSource = new JRBeanCollectionDataSource(ejecutaPago.getLstPagosHechos());
//			for (Resumen_pagos rp : ejecutaPago.getLstPagosHechos()) {
//				rps=rp;
//				break;
//			}
			
			String fecha = "";
			try {
				SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
			} catch (Exception e) {
			}
			
			
			this.titulo = "Listado de pagos de la fecha " + fecha;
		}
		else{
			parameters.put("plantilla", reporteName);
		}

		parameters.put("titulo", this.titulo);
		String parnivel = GetStringNiveles();
		parameters.put("nivel", parnivel);

		Enumeration paramNames = req.getParameterNames();
		while (paramNames.hasMoreElements()) {

			String paramName = (String) paramNames.nextElement(); // nombre
			String[] paramValues = req.getParameterValues(paramName); // valor (
																		// paramValues[0]
																		// )
			// System.out.println(paramName + " = " + paramValues[0]);

			if (paramName.equals("reporte"))
				this.reporte = paramValues[0];
			if (paramName.equals("tipo"))
				this.tipo = paramValues[0];
			if (paramName.substring(0, 3).equals("ps_"))
				parameters.put(paramName, paramValues[0]);
			if (paramName.substring(0, 3).equals("pi_"))
				parameters.put(paramName, Integer.parseInt(paramValues[0]));
			if (paramName.substring(0, 3).equals("pl_"))
				parameters.put(paramName, Long.parseLong(paramValues[0]));

			if (paramName.substring(0, 3).equals("pr_")) {
				if (!NOSELECTED.equals(paramValues[0])) {
					parameters.put(paramName, paramValues[0]);
				} else {
					parameters.put(paramName, "N/A");
				}
			}
		}
	}

	public void generarPdf(String nombreReporte) {

		try {			
		    //String fileName = getClass().getClassLoader().getResource("com/foo/myproject/reports/TestReport.jrxml").getFile();
		    String fileName = sc.getRealPath(rutaReporte + File.separator + parameters.get("plantilla") + ".jrxml");

		    File theFile = new File(fileName);
		    JasperDesign jasperDesign = JRXmlLoader.load(theFile);

		    JRQuery oldQuery = jasperDesign.getQuery();
		    
		    if(oldQuery!=null){
			    //Build a new query
			    String theQuery = AlteraQueryDinamico(oldQuery.getText());
		    	// update the data query
			    JRDesignQuery newQuery = new JRDesignQuery();
			    newQuery.setText(theQuery);
			    System.out.println("query final = " + theQuery);
			    jasperDesign.setQuery(newQuery);		    	
		    }

		    //JasperCompileManager.compileReportToFile(jasperDesign, sc.getRealPath(rutaReporte + File.separator + parameters.get("plantilla") + ".jasper"));
		    JasperReport  rep_compilado = JasperCompileManager.compileReport(jasperDesign); 
		    
			//JasperCompileManager.compileReportToFile(sc.getRealPath(rutaReporte + File.separator + parameters.get("plantilla") + ".jrxml"));
			File reportFile = new File(sc.getRealPath(rutaReporte + File.separator + parameters.get("plantilla") + ".jasper"));
			byte[] bytes = null;
			JasperPrint reportllenado;
			if("pagos".equalsIgnoreCase((String)parameters.get("plantilla"))||"p001".equalsIgnoreCase((String)parameters.get("plantilla"))||"avance_cobertura_VIVIENDA".equalsIgnoreCase((String)parameters.get("plantilla"))){
				//bytes = JasperRunManager.runReportToPdf(reportFile.getPath(), parameters, this.collectionDataSource);
				reportllenado = JasperFillManager.fillReport(rep_compilado, parameters, this.collectionDataSource); //llenado en memoria para el reporte
			}else{
				setConexion();	
				//bytes = JasperRunManager.runReportToPdf(reportFile.getPath(), parameters, conn);	
				reportllenado = JasperFillManager.fillReport(rep_compilado, parameters, conn); //llenado en memoria para el reporte							
			}

			ByteArrayOutputStream outputByteArray= new ByteArrayOutputStream();
			JRPdfExporter pdfExporter = new JRPdfExporter();
			
			pdfExporter.setParameter(JRExporterParameter.JASPER_PRINT, reportllenado);
			pdfExporter.setParameter(JRExporterParameter.OUTPUT_STREAM, outputByteArray);
			
			pdfExporter.exportReport();
			
			ServletOutputStream salida = res.getOutputStream();
			
			res.setContentType("application/pdf");
			res.addHeader("Content-Disposition", "attachment; filename="+ parameters.get("reporte") + ".pdf");
			//res.setContentLength(bytes.length);
	
			//ServletOutputStream ouputStream = res.getOutputStream();
			salida.write(outputByteArray.toByteArray());
			
			//ouputStream.write(bytes, 0, bytes.length);
			//ouputStream.flush();
			//ouputStream.close();
			salida.flush();
			salida.close();

		} catch (JRException e) {
			System.out.println("Error:" + e.getMessage() + " " + e);
		} catch (Exception e) {
			e.printStackTrace();
		}finally{ 
            try{
            	if(conn != null){
            		conn.close();
            	}
            } catch( Exception exx ) { exx.printStackTrace(); }
         }
	}
	


	public void generarEXCEL(String nombreReporte) {
		try {			
		    //String fileName = getClass().getClassLoader().getResource("com/foo/myproject/reports/TestReport.jrxml").getFile();
		    String fileName = sc.getRealPath(rutaReporte + File.separator + parameters.get("plantilla") + ".jrxml");

		    File theFile = new File(fileName);
		    JasperDesign jasperDesign = JRXmlLoader.load(theFile);

		    JRQuery oldQuery = jasperDesign.getQuery();
		    
		    //Build a new query
		    //System.out.println("antes =" + oldQuery.getText());
		    String theQuery = AlteraQueryDinamico(oldQuery.getText());
		    //System.out.println("despues =" + theQuery);

		    // update the data query
		    JRDesignQuery newQuery = new JRDesignQuery();
		    		    
		    newQuery.setText(theQuery);
		    jasperDesign.setQuery(newQuery);

		    
		    //JasperCompileManager.compileReportToFile(jasperDesign, sc.getRealPath(rutaReporte + File.separator + parameters.get("plantilla") + ".jasper"));  
		    JasperReport  rep_compilado = JasperCompileManager.compileReport(jasperDesign); 
		    
		    //----------------
		    JasperPrint reportllenado;
			if("pagos".equalsIgnoreCase((String)parameters.get("plantilla"))||"p001".equalsIgnoreCase((String)parameters.get("plantilla"))||"avance_cobertura_VIVIENDA".equalsIgnoreCase((String)parameters.get("plantilla"))){
				reportllenado = JasperFillManager.fillReport(rep_compilado, parameters, this.collectionDataSource); //llenado en memoria para el reporte

			}else{
				setConexion();	
				reportllenado = JasperFillManager.fillReport(rep_compilado, parameters, conn); //llenado en memoria para el reporte							
			}				
			
			ByteArrayOutputStream outputByteArray= new ByteArrayOutputStream();
			JRXlsExporter xlsExporter = new JRXlsExporter();
			
			xlsExporter.setParameter(JRExporterParameter.JASPER_PRINT, reportllenado);
			xlsExporter.setParameter(JRExporterParameter.OUTPUT_STREAM, outputByteArray);
			
			xlsExporter.exportReport();
			
			ServletOutputStream salida = res.getOutputStream();
			res.setContentType("application/vnd.ms-excel");

			salida.write(outputByteArray.toByteArray());
			

		} catch (JRException e) {
			System.out.println("Error:" + e.getMessage() + " " + e);
		} catch (Exception e) {
			e.printStackTrace();
		}finally{ 
            try{
            	if(conn != null){
            		conn.close();
            	}
            } catch( Exception exx ) { exx.printStackTrace(); }
         }

	}
	


	
	public void generarCSV(String nombreReporte) {
		try {			
		    //String fileName = getClass().getClassLoader().getResource("com/foo/myproject/reports/TestReport.jrxml").getFile();
		    String fileName = sc.getRealPath(rutaReporte + File.separator + parameters.get("plantilla") + ".jrxml");

		    File theFile = new File(fileName);
		    JasperDesign jasperDesign = JRXmlLoader.load(theFile);

		    JRQuery oldQuery = jasperDesign.getQuery();
		    
		    //Build a new query
		    //System.out.println("antes =" + oldQuery.getText());
		    String theQuery = AlteraQueryDinamico(oldQuery.getText());
		    //System.out.println("despues =" + theQuery);

		    // update the data query
		    JRDesignQuery newQuery = new JRDesignQuery();
		    		    
		    newQuery.setText(theQuery);
		    jasperDesign.setQuery(newQuery);

		    
		    //JasperCompileManager.compileReportToFile(jasperDesign, sc.getRealPath(rutaReporte + File.separator + parameters.get("plantilla") + ".jasper"));  
		    JasperReport  rep_compilado = JasperCompileManager.compileReport(jasperDesign); 
		    
		    //----------------
		    JasperPrint reportllenado;
			if("pagos".equalsIgnoreCase((String)parameters.get("plantilla"))||"p001".equalsIgnoreCase((String)parameters.get("plantilla"))||"avance_cobertura_VIVIENDA".equalsIgnoreCase((String)parameters.get("plantilla"))){
				reportllenado = JasperFillManager.fillReport(rep_compilado, parameters, this.collectionDataSource); //llenado en memoria para el reporte

			}else{
				setConexion();	
				reportllenado = JasperFillManager.fillReport(rep_compilado, parameters, conn); //llenado en memoria para el reporte							
			}				
			
			ByteArrayOutputStream outputByteArray= new ByteArrayOutputStream();
			JRCsvExporter textExporter = new JRCsvExporter();
			
			textExporter.setParameter(JRCsvExporterParameter.FIELD_DELIMITER, "|");
			textExporter.setParameter(JRExporterParameter.JASPER_PRINT, reportllenado);
			textExporter.setParameter(JRExporterParameter.OUTPUT_STREAM, outputByteArray);

			textExporter.exportReport();
			
			byte[] salidaBytes = outputByteArray.toByteArray();  

			
			ServletOutputStream salida = res.getOutputStream();
			res.setContentType("text/plain");
			res.setContentLength(salidaBytes.length);
			
			salida.write(salidaBytes);
			//salida.print(salidaBytes.toString());
			salida.flush();
			salida.close();
			
			

		} catch (JRException e) {
			System.out.println("Error:" + e.getMessage() + " " + e);
		} catch (Exception e) {
			e.printStackTrace();
		}finally{ 
            try{
            	if(conn != null){
            		conn.close();
            	}
            } catch( Exception exx ) { exx.printStackTrace(); }
         }

	}
	
	
	
	
	public void generarHTML(String nombreReporte) {
		System.out.println("Entro HTML");
		try {			
		    //String fileName = getClass().getClassLoader().getResource("com/foo/myproject/reports/TestReport.jrxml").getFile();
		    String fileName = sc.getRealPath(rutaReporte + File.separator + parameters.get("plantilla") + ".jrxml");

		    File theFile = new File(fileName);
		    JasperDesign jasperDesign = JRXmlLoader.load(theFile);

		    JRQuery oldQuery = jasperDesign.getQuery();
		    
		    //Build a new query
		    //System.out.println("antes =" + oldQuery.getText());
		    String theQuery = AlteraQueryDinamico(oldQuery.getText());
		    System.out.println("despues =" + theQuery);

		    // update the data query
		    JRDesignQuery newQuery = new JRDesignQuery();
		    
		    //System.out.println("query salida = "+theQuery);
		    
		    newQuery.setText(theQuery);
		    jasperDesign.setQuery(newQuery);

		    
		    JasperCompileManager.compileReportToFile(jasperDesign, sc.getRealPath(rutaReporte + File.separator + parameters.get("plantilla") + ".jasper"));
		    JasperReport  rep_compilado = JasperCompileManager.compileReport(jasperDesign); 
		    
		    
		    //----------------
		    JasperPrint reportllenado;
			//JasperCompileManager.compileReportToFile(sc.getRealPath(rutaReporte + File.separator + parameters.get("plantilla") + ".jrxml"));
			File reportFile = new File(sc.getRealPath(rutaReporte + File.separator + parameters.get("plantilla") + ".jasper"));
			//byte[] bytes = null;
			if("pagos".equalsIgnoreCase((String)parameters.get("plantilla"))||"p001".equalsIgnoreCase((String)parameters.get("plantilla"))||"avance_cobertura_VIVIENDA".equalsIgnoreCase((String)parameters.get("plantilla"))){
				reportllenado = JasperFillManager.fillReport(rep_compilado, parameters, this.collectionDataSource); //llenado en memoria para el reporte
				JasperRunManager.runReportToHtmlFile(reportFile.toString(), parameters, this.collectionDataSource); //generando en archivo reporte para generar los recursos PARAPELO	

			}else{
				setConexion();	
				reportllenado = JasperFillManager.fillReport(rep_compilado, parameters, conn); //llenado en memoria para el reporte
				JasperRunManager.runReportToHtmlFile(reportFile.toString(), parameters, conn); //generando en archivo reporte para generar los recursos PARAPELO	
				
			}			
	
			
			ByteArrayOutputStream outputByteArray= new ByteArrayOutputStream();
			JRHtmlExporter htmlExporter = new JRHtmlExporter();
			

			
			htmlExporter.setParameter(JRExporterParameter.JASPER_PRINT, reportllenado);
			htmlExporter.setParameter(JRExporterParameter.OUTPUT_STREAM, outputByteArray);
			htmlExporter.setParameter(JRHtmlExporterParameter.IMAGES_URI,"static/reportes/"+parameters.get("plantilla")+".html_files/");
			//htmlExporter.setParameter(JRHtmlExporterParameter.IMAGES_MAP, new HashMap());
			
			htmlExporter.exportReport();
//			System.out.write(outputByteArray.toByteArray());
			
			
			
			ServletOutputStream salida = res.getOutputStream();
			res.setContentType("text/html");
			//salida.println("<iframe src='"+salidaHTML +"' ></iframe>");
			salida.write(outputByteArray.toByteArray());
			

		} catch (JRException e) {
			System.out.println("Error:" + e.getMessage() + " " + e);
		} catch (Exception e) {
			e.printStackTrace();
		}finally{ 
            try{
            	if(conn != null){
            		conn.close();
            	}
            } catch( Exception exx ) { exx.printStackTrace(); }
         }
	}

	
	
	
	// .......................:::::::::::::::::::   Rutina del AlterQuery   :::::::::::::::::::..............................
	
	public String AlteraQueryDinamico(String sql){
        String marcadorParametro = ":";
        String valorPar = "";
        Map <String,String> valorParametros = new HashMap<String, String>();


        
		Enumeration paramNames = req.getParameterNames();
		while (paramNames.hasMoreElements()) {
	        String paramName = (String) paramNames.nextElement(); // nombre
			String[] paramValues = req.getParameterValues(paramName); // valor (
			if (paramName.substring(0, 3).equals("ps_") || paramName.substring(0, 3).equals("pi_") || paramName.substring(0, 3).equals("pl_")) {
	        valorParametros.put(paramName, paramValues[0]);
			}
		}

        return reemplazarParametrosEnSql(sql, valorParametros, marcadorParametro);
	}
	
    public String reemplazarParametrosEnSql(String sqlComplex, Map<String,String> valorParametros, String marcadorParametro){
        
        if(sqlComplex.contains(marcadorParametro)){
            
            int beginIndex = sqlComplex.indexOf("{");
            int betweenIndex = sqlComplex.indexOf(marcadorParametro);
            int endIndex = sqlComplex.indexOf("}");
            
            if(beginIndex < betweenIndex && betweenIndex < endIndex){

                String cadenaInicial = sqlComplex.substring(0,beginIndex);
                String cadenaIntermedia = sqlComplex.substring(beginIndex+1, endIndex);
                String cadenaFinal = sqlComplex.substring(endIndex+1,sqlComplex.length()); 
                                
                String parametroReemplazado = reemplazarParametro(cadenaIntermedia, valorParametros, marcadorParametro);
                
                String cadenaSql = cadenaInicial + parametroReemplazado + cadenaFinal;
                
                sqlComplex = reemplazarParametrosEnSql(cadenaSql, valorParametros, marcadorParametro);
            } 
        }
        return sqlComplex;
    }

    private String reemplazarParametro(String sqlComplex, Map<String,String> valorParametros, String marcadorParametro){

        int beginIndex = sqlComplex.indexOf(marcadorParametro);
        int endIndex = sqlComplex.lastIndexOf(marcadorParametro);

        String antesParametro = sqlComplex.substring(0,beginIndex);
        String parametro = sqlComplex.substring(beginIndex+1, endIndex);
        String despuesParametro = sqlComplex.substring(endIndex+1,sqlComplex.length()); 
        
        String parametroReemplazado = "";
        
        if(valorParametros.containsKey(parametro)){                    
            
            parametroReemplazado = antesParametro + valorParametros.get(parametro) + despuesParametro;                            
        }                
        
        return parametroReemplazado;                
    }      
    
    
    
    private String GetStringNiveles(){
    	String niveles = "";

        

    	return niveles;
    }
    

	
}
